package com.sun.service;

import com.sun.api.constellation;
import com.sun.entity.AccessToken;
import com.sun.entity.LocationMessage;
import com.sun.entity.Message;
import com.sun.entity.TextMessage;
import com.thoughtworks.xstream.XStream;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class WxService {
	private static final String TOKEN = "abc";
	private static final String GET_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	private static final String APPID = "wx4aff8b498985ae87";
	private static final String APPSECRET = "5fbe540cfff2634e958481b2152aa029";
	private static AccessToken accessToken;

	/**
	 * 获取新token
	 */
	private static void getToken() {
		String url = GET_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
		String tokenStr = constellation.get(url);
//		System.out.println(tokenStr);
		JSONObject jsonObject = JSONObject.fromObject(tokenStr);
		String accessTokenStr = jsonObject.getString("access_token");
		long expiresIn = jsonObject.optInt("expires_in");
		accessToken = new AccessToken(accessTokenStr, expiresIn);
	}

	/**
	 * 获取当前有效token
	 *
	 * @return
	 */
	public static String getAccessToken() {
		if (accessToken == null || accessToken.IsExpired()) {
			getToken();
		}
		return accessToken.getToken();
	}

	/**
	 * 验证请求是否来自微信
	 *
	 * @param timestamp
	 * @param nonce
	 * @param signature
	 * @return
	 */
	public static boolean check(String timestamp, String nonce, String signature) {
		//		 1）将token、timestamp、nonce三个参数进行字典序排序
		String[] strings = new String[]{TOKEN, timestamp, nonce};
		Arrays.sort(strings);
		//		 2）将三个参数字符串拼接成一个字符串进行sha1加密
		String string = strings[0] + strings[1] + strings[2];
		String mysig = sha1(string);
		//		 3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
		if (mysig.equals(signature)) {
			return true;
		}
		return false;
	}

	/**
	 * sha1加密
	 *
	 * @param string
	 * @return
	 */
	private static String sha1(String string) {
		String str = null;
		try {
			// 获取加密对象
			MessageDigest messageDigest = MessageDigest.getInstance("sha1");
			// 加密
			byte[] digest = messageDigest.digest(string.getBytes());
			// 处理加密数组
			char[] chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
			StringBuffer stringBuffer = new StringBuffer();
			for (byte b : digest) {
				stringBuffer.append(chars[(b >> 4) & 15]);
				stringBuffer.append(chars[b & 15]);
			}
			str = stringBuffer.toString();

		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return str;
	}

	/**
	 * 解析xml数据包
	 *
	 * @param inputStream
	 * @return
	 */
	public static Map<String, String> parseRequest(InputStream inputStream) {
		Map<String, String> map = new HashMap<>();
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(inputStream);
			// 获取根节点
			Element root = document.getRootElement();
			List<Element> elements = root.elements();
			for (Element element : elements) {
				map.put(element.getName(), element.getStringValue());
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 以xml格式返回消息
	 *
	 * @param requestMap
	 * @return
	 */
	public static String getResponse(Map<String, String> requestMap) {
		Message message = null;
		String xml = null;
		String msgType = requestMap.get("MsgType");
		switch (msgType) {
			case "text": {
				message = new TextMessage(requestMap, dealTextMessage(requestMap.get("Content")));
				XStream stream = new XStream();
				stream.processAnnotations(TextMessage.class);
				xml = stream.toXML(message);
			}
			break;
			case "image":
				break;
			case "voice":
				break;
			case "video":
				break;
			case "shortvideo":
				break;
			case "location": {
				message = new LocationMessage(requestMap);
				XStream stream = new XStream();
				stream.processAnnotations(LocationMessage.class);
				xml = stream.toXML(message);
			}
			break;
			case "link":
				break;
		}
		return xml;
	}

	/**
	 * 处理文本信息 星座查询
	 * @param msg
	 * @return
	 */
	public static String dealTextMessage(String msg) {
		String string = null;
		// 查询星座运势
		String result = constellation.getRequest1(msg);
		JSONObject jsonObject = JSONObject.fromObject(result);
		int error_code = jsonObject.optInt("error_code");
		if (error_code != 0) {
			if (error_code == 205802) {
				string = "错误的星座名称\n" + jsonObject.getString("reason");
			} else if (error_code == 205801) {
				string = "错误的运势类型";
			}
		} else if (error_code == 0){
			String name = jsonObject.getString("name");
			String date = jsonObject.getString("datetime");
			String QFriend = jsonObject.getString("QFriend");
			String color = jsonObject.getString("color");
			String summary = jsonObject.getString("summary");
			int number = jsonObject.optInt("number");
			string = "星座名称：" + name + "\n" +
					"日期：" + date + "\n" +
					"幸运色：" + color + "\n" +
					"速配星座：" + QFriend + "\n" +
					"幸运数字：" + number + "\n" +
					"今日概述：" + summary;
		}
		return string;
	}
}
